package com.bjpowernode.boss.mvc.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjpowernode.boss.PowerBossApplication;
import com.bjpowernode.boss.common.event.UserConfigMailEvent;
import com.bjpowernode.boss.constants.BoosConst;
import com.bjpowernode.boss.constants.KeyConst;
import com.bjpowernode.boss.domain.UserInfo;
import com.bjpowernode.boss.domain.UserPayConfig;
import com.bjpowernode.boss.domain.UserPayInfo;
import com.bjpowernode.boss.enums.ajax.Code;
import com.bjpowernode.boss.enums.buz.PublicStatus;
import com.bjpowernode.boss.exception.BossException;
import com.bjpowernode.boss.mapper.UserInfoMapper;
import com.bjpowernode.boss.mapper.UserPayConfigMapper;
import com.bjpowernode.boss.mapper.UserPayInfoMapper;
import com.bjpowernode.boss.mvc.model.mail.MailProperty;
import com.bjpowernode.boss.mvc.model.query.KqConfigQuery;
import com.bjpowernode.boss.mvc.model.query.UserPayConfigQuery;
import com.bjpowernode.boss.mvc.model.query.WxConfigQuery;
import com.bjpowernode.boss.mvc.service.UserPayConfigService;
import com.bjpowernode.boss.utils.NoUtil;
import com.bjpowernode.boss.utils.RedisUtil;
import jakarta.annotation.Resource;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 *
 */
@Service
public class UserPayConfigServiceImpl extends ServiceImpl<UserPayConfigMapper, UserPayConfig> implements UserPayConfigService {

    @Resource
    private UserPayConfigMapper userPayConfigMapper;

    @Resource
    private UserPayInfoMapper userPayInfoMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private ApplicationEventPublisher eventPublisher;

    @Override
    public IPage<UserPayConfig> loadPayConfigData(Integer pageNo, Integer pageSize) {
        return userPayConfigMapper.selectPage(new Page<>(pageNo, pageSize), new LambdaQueryWrapper<UserPayConfig>().orderByDesc(UserPayConfig::getEditTime));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createPayConfigEdit(UserPayConfigQuery userPayConfigQuery) {
        // 查询数据库中是否存在该数据
        UserPayConfig userPayConfig = userPayConfigMapper
                .selectOne(
                        new LambdaQueryWrapper<UserPayConfig>()
                                .eq(UserPayConfig::getPayProductCode, userPayConfigQuery.getProductCode())
                                .eq(UserPayConfig::getUserNo, userPayConfigQuery.getUserNo()));
        if (userPayConfig != null) {
            throw new BossException(Code.PAY_CONFIG_EXIST);
        }

        // 添加数据
        // 添加 userPayConfig
        userPayConfig = new UserPayConfig();
        userPayConfig.setId(NoUtil.uuid());
        userPayConfig.setUserNo(userPayConfigQuery.getUserNo());
        userPayConfig.setShopName(userPayConfigQuery.getShopName());
        userPayConfig.setPayProductCode(userPayConfigQuery.getProductCode());
        userPayConfig.setPayProductName(userPayConfigQuery.getProductName());
        userPayConfig.setRiskDay(Integer.valueOf(userPayConfigQuery.getRiskDay()));
        userPayConfig.setAppKey(NoUtil.uuid());
        userPayConfig.setAppSecret(NoUtil.uuid());
        userPayConfig.setMerchantServerIp(userPayConfigQuery.getIpList());
        userPayConfig.setAutoSett(userPayConfigQuery.getAutoSett());
        userPayConfig.setRemark("创建商户支付配置");
        userPayConfig.setEditTime(new Date());
        userPayConfig.setStatus(PublicStatus.ENABLE.name());
        userPayConfigMapper.insert(userPayConfig);

        // 创建一个map集合 , 存储下面创建后的 userpayinfo
        Map<String , String> payConfigMap = new HashMap<>();
        // 添加 userpayinfo
        KqConfigQuery kqConfig = userPayConfigQuery.getKqConfig();
        if (kqConfig != null && StrUtil.isNotBlank(kqConfig.getMerchId() )
                && StrUtil.isNotBlank(kqConfig.getPublicFile())
                && StrUtil.isNotBlank(kqConfig.getPrivateFile())
                && StrUtil.isNotBlank(kqConfig.getQueryKey())) {
            UserPayInfo userPayInfo = new UserPayInfo();
            userPayInfo.setId(NoUtil.uuid());
            userPayInfo.setPayProductCode(userPayConfigQuery.getProductCode());
            userPayInfo.setUserNo(userPayConfigQuery.getUserNo());
            userPayInfo.setShopName(userPayConfigQuery.getShopName());
            userPayInfo.setPayWayCode(BoosConst.PAY_WAY_CODE_KUAIQIAN);
            userPayInfo.setPayWayName(PowerBossApplication.DIC_PAY_WAY_NAME_MAP.get(BoosConst.PAY_WAY_CODE_KUAIQIAN));
            userPayInfo.setPayConfig(JSONUtil.toJsonStr(userPayConfigQuery.getKqConfig()));
            userPayInfo.setRemark("创建商户支付信息_快钱");
            userPayInfo.setEditTime(new Date());
            userPayInfo.setStatus(PublicStatus.ENABLE.name());
            userPayInfoMapper.insert(userPayInfo);
            // 添加快钱配置
            payConfigMap.put(userPayInfo.getPayWayCode() , userPayInfo.getPayConfig());
        }

        // 添加判断 , 是否存在
        WxConfigQuery wxConfig = userPayConfigQuery.getWxConfig();
        if (wxConfig != null && StrUtil.isNotBlank(wxConfig.getAppId()) && StrUtil.isNotBlank(wxConfig.getMerchId())) {
            UserPayInfo userPayInfo = new UserPayInfo();
            userPayInfo.setId(NoUtil.uuid());
            userPayInfo.setPayProductCode(userPayConfigQuery.getProductCode());
            userPayInfo.setUserNo(userPayConfigQuery.getUserNo());
            userPayInfo.setShopName(userPayConfigQuery.getShopName());
            userPayInfo.setPayWayCode(BoosConst.PAY_WAY_CODE_WEIXIN);
            userPayInfo.setPayWayName(PowerBossApplication.DIC_PAY_WAY_NAME_MAP.get(BoosConst.PAY_WAY_CODE_WEIXIN));
            userPayInfo.setPayConfig(JSONUtil.toJsonStr(userPayConfigQuery.getWxConfig()));
            userPayInfo.setRemark("创建商户支付信息_微信");
            userPayInfo.setEditTime(new Date());
            userPayInfo.setStatus(PublicStatus.ENABLE.name());
            userPayInfoMapper.insert(userPayInfo);
            // 添加快钱配置
            payConfigMap.put(userPayInfo.getPayWayCode() , userPayInfo.getPayConfig());
        }

        // 将数据 添加到 redis中去
        // 参数 -->  userNo  |  productcode  |   appkey   |  appsecret   |  merchantserverip | payconfigMap
        cacheUserPayConfigToRedis(userPayConfigQuery.getUserNo(),
                userPayConfig.getPayProductCode(),
                userPayConfig.getAppKey(),
                userPayConfig.getAppSecret(),
                userPayConfig.getMerchantServerIp(),
                payConfigMap);

        // 异步发送 email给 指定商家
        // 发送数据
        MailProperty mailProperty = new MailProperty();
        mailProperty.setFrom("devhjb@163.com");
        // 获取 商户信息 中的邮箱
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserNo, userPayConfigQuery.getUserNo()));
        mailProperty.setTo(new String[]{userInfo.getUserEmail()});
        mailProperty.setSubject("商户支付基本信息");
        // 定义文本内容  ---> 拼接
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("商户号:").append(userInfo.getUserNo()).append("<br/>");
        stringBuilder.append("商户名称:").append(userInfo.getShopName()).append("<br/>");
        stringBuilder.append("支付产品编号:").append(userPayConfig.getPayProductCode()).append("<br/>");
        stringBuilder.append("访问appKey:").append(userPayConfig.getAppKey()).append("<br/>");
        stringBuilder.append("访问appSecret:").append(userPayConfig.getAppSecret()).append("<br/>");
        mailProperty.setText(stringBuilder.toString());
        // 使用springevent
        // 3.发布事件Spring 提供的ApplicationEventPublisher来发布自定义事件
        // * 	--->在实用类中 添加applicationEventPublisher的bean对象
        // * 	---> 通过 new自定义事件类对象 , 调用applicationEventPublisher的bean对象的方法
        UserConfigMailEvent mailEvent = new UserConfigMailEvent(this, mailProperty);
        eventPublisher.publishEvent(mailEvent);
    }

    private void cacheUserPayConfigToRedis(String userNo,
                                           String payProductCode,
                                           String appKey,
                                           String appSecret,
                                           String merchantServerIp,
                                           Map<String, String> payConfigMap) {
        // 定义key
        String payConfigKey = KeyConst.USER_PAY_CONFIG + userNo + "#" + payProductCode;

        // 将形参转换为 json对象
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("payProductCode", payProductCode);
        jsonObject.set("appKey", appKey);
        jsonObject.set("appSecret", appSecret);
        jsonObject.set("ipList", merchantServerIp);

        //  将参数集合 封装为map
        Map<String , String> data = new HashMap<>();
        // 将数据存储 map  --->  将json对象 转换为 json字符串 添加到map中
        data.put("CONFIG", jsonObject.toJSONString(0));
        // 将 payConfigMap 所有值 直接添加到 data中
        data.putAll(payConfigMap);

        // 添加到redis中
        redisUtil.setHashValue(payConfigKey , data);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeUserPayInfoByUserNo(String userNo) {
        // 该业务 需要进行关联删除
        // 即删除 user_pay_config 表中的数据
        int delete = userPayConfigMapper.delete(new LambdaQueryWrapper<UserPayConfig>().eq(UserPayConfig::getUserNo, userNo));
        if (delete == 0) {
            return;
        }
        // 删除 user_pay_info 表中数据
        userPayInfoMapper.delete(new LambdaQueryWrapper<UserPayInfo>().eq(UserPayInfo::getUserNo, userNo));
    }
}
